const kurento = require("kurento-client");
var mqtt = require('mqtt');
var path = require('path');
var fs = require('fs');
var format = require('string-format');
const e = require("express");
format.extend(String.prototype);

class TRtcMonitor {
    constructor() {
        this.config = {
            kmsUrl: "wss://wss.hhdata.cn:8433/kurento",
            tagKey: "rtcV10",
            kmsFlag: "rtcV10",
            turnUrl: "kurento:kurento@223.68.161.139:3478?transport=tcp",
            stunHost: "223.68.161.139",
            stunPort: 3478,
            schedulePipes: [
                {}
            ]
        }
        this.kmsClient = null;
        this.kmsObjs = {};
    }
    checkClient() {
        var me = this;
        return new Promise((success, faild) => {
            try {
                if (!me.kmsClient || me.kmsClient == null) {
                    success(false);
                } else {
                    me.kmsClient.getServerManager(function(eer, _svr) {
                        if (eer || _svr == null) {
                            success(false);
                        } else {
                            success(true);
                        }
                    });
                }
            } catch (eer) {
                console.log(eer);
                success(false);
            }
        })
    }
    createNewClient() {
        var me = this;
        return new Promise((success, faild) => {
            try {
                kurento(me.config.kmsUrl, function(erClient, _client) {
                    me.kmsClient = _client;
                    _client.getServerManager().then(_svr => {
                        _client.svr = _svr;
                        /*
                        _svr.on('ObjectCreated', (data => {
                            me.kmsObjs[data.objectId] = {
                                id: data.objectId,
                                tags: data.tags,
                                info: me.tags2Info(data.tags)
                            };
                            me.saveLog('ObjectCreated', me.kmsObjs[data.objectId]);
                        }));
                        */
                        _svr.on('ObjectDestroyed', (data => {
                            me.saveLog('ObjectDestroyed', me.kmsObjs[data.objectId]);
                            if (me.kmsObjs[data.objectId]) {
                                delete me.kmsObjs[data.objectId];
                            }
                        }));
                        success(me.kmsClient);
                    })
                })
            } catch (eer) {
                console.log(eer);
                success();
            }
        })
    }
    updateKmsObjInfo(objId) {
        var me = this;
        return new Promise((success, faild) => {
            try {
                var kmsObj = me.kmsObjs[objId];
                var obj = null;
                me.kmsClient.getMediaobjectById(objId).then(_obj => {
                    obj = _obj;
                    return obj.getName();
                }).then(_name => {
                    kmsObj.name = _name;
                    return obj.getTags();
                }).then(_tags => {
                    kmsObj.tags = _tags;
                    kmsObj.info = me.tags2Info(_tags);
                    success({
                        obj: obj,
                        objInfo: kmsObj
                    });
                });
            } catch (eer) {
                console.log(eer);
                success();
            }
        })
    }
    setKmsObjInfo(objId, objName, info) {
        var me = this;
        return new Promise((success, faild) => {
            try {
                me.getClient().then(_client => {
                    return _client.getMediaobjiectById(objId);
                }).then(_obj => {
                    if (_obj && _obj != null) {
                        _obj.setName(objName).then(_ => {
                            return _obj.addTag(me.config.tagKey, JSON.stringify(info));
                        }).then(_ => {
                            me.kmsObjs[objId] = {
                                id: objId,
                                tags: JSON.stringify(info),
                                info: info,
                                name: objName
                            };
                            success(1);
                        })
                    } else {
                        success(-1);
                    }
                })
            } catch (eer) {
                console.log(eer);
                success();
            }
        })
    }
    getClient() {
        var me = this;
        return new Promise((success, faild) => {
            try {
                me.checkClient().then(flag => {
                    if (flag) {
                        success(me.kmsClient);
                    } else {
                        me.createNewClient().then(_ => {
                            success(me.kmsClient);
                        })
                    }
                })
            } catch (eer) {
                console.log(eer);
                success();
            }
        })
    }
    scanObjs() {
        var me = this;
        return new Promise((success, faild) => {
            try {
                var kmsObjs = {};
                me.getClient().then(client => {
                    var svr = client.svr;
                    return svr.getPipelines();
                }).then(pipes => {
                    var assignObj = (obj) => {
                        return new Promise((s, f) => {
                            try {
                                obj.getTags().then(_tags => {
                                    var objInfo = {
                                        id: obj.id,
                                        tags: _tags,
                                        info: me.tags2Info(_tags)
                                    };
                                    kmsObjs[objInfo.id] = objInfo;
                                    return obj.getName();
                                }).then(_name => {
                                    obj.name = _name;
                                    kmsObjs[obj.id].name = _name;
                                    return obj.getChildren();
                                }).then(items => {
                                    var loadItem = function() {
                                        if (items.length > 0) {
                                            var itemObj = items.shift();
                                            assignObj(itemObj).then(_ => {
                                                loadItem();
                                            })
                                        } else {
                                            s();
                                        }
                                    }
                                    loadItem();
                                })
                            } catch (e) {
                                console.log(e);
                                s();
                            }
                        })
                    }
                    var loadPipe = function() {
                        if (pipes.length > 0) {
                            var pipe = pipes.shift();
                            assignObj(pipe).then(_ => {
                                loadPipe();
                            })
                        } else {
                            me.kmsObjs = kmsObjs;
                            me.saveLog("scan", me.kmsObjs);
                            success();
                        }
                    };
                    loadPipe();
                })
            } catch (eer) {
                console.log(eer);
                success();
            }
        })
    }
    tags2Info(tags) {
        var me = this;
        var info = {};
        try {
            var arrs = tags.filter(t => {
                return t.key == me.config.tagKey;
            })
            if (arrs.length > 0) {
                var infoJson = arrs[0].value;
                info = JSON.parse(infoJson);
            }
        } catch (eer) {
            console.log(eer);
        }
        return info;
    }
    saveLog(action, info) {
        var me = this;
        return new Promise((success, faild) => {
            try {
                console.log(action, info);
                success();
            } catch (eer) {
                console.log(eer);
                success();
            }
        })
    }
    regist2WebSvr(webSvr) {
        var me = this;
        if (webSvr && webSvr != null && webSvr.registRoute) {
            var respJson = function(result, response) {
                try {
                    response.send(JSON.stringify(result));
                } catch (eer) {
                    console.log(eer);
                }
            }
            webSvr.registRoute("rtc", "rtcStatus", "getKmsObjs", function(result, request, response) {
                try {
                    result.data = me.kmsObjs;
                    respJson(result, response);
                } catch (err) {
                    console.log(err);
                    respJson(result, response);
                }
            });
            webSvr.registRoute("rtc", "rtcStatus", "setObjInfo", function(result, request, response) {
                try {
                    var objId = result.ps.objid;
                    var objName = result.ps.objName;
                    var infoJson = result.ps.infoJson;
                    var info = {};
                    try {
                        info = JSON.parse(infoJson);
                    } catch (eer) {
                        console.log(eer);
                    }
                    me.setKmsObjInfo(objId, objName, info).then(_status => {
                        result.data = {
                            id: objId,
                            name: objName,
                            info: info,
                            status: status
                        };
                        respJson(result, response);
                    })
                } catch (err) {
                    console.log(err);
                    respJson(result, response);
                }
            });
        }
    }
    start() {
        var me = this;
        try {
            me.getClient().then(_client => {
                setTimeout(function() {
                    me.start();
                }, 2 * 60 * 1000);
            })
        } catch (er) {
            console.log(er);
        }
    }
}


module.exports = {
    TRtcMonitor: TRtcMonitor
}